﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Base\IState.cs
 * Description  :     Interface for states
 * Change log   :     -2011: (it was originally part of SimGine)
 *                    (c) Ali Khalili and Amir Jalaly
 * To Do        :
 ************************************************************************/
using System;
using System.Collections.Generic;


namespace SMLib.Base
{

	/// <summary>
    /// Interface for states [used as vertex/state in DiGraph]
    /// </summary>
    /// <typeparam name="TRANSITIONTYPE">the kind of transition</typeparam>
    public interface IState<TRANSITIONTYPE>
    {
        /// <summary>
        /// List of transitions to the next states
        /// </summary>
        List<TRANSITIONTYPE> Transitions
        {
            get;
        }
    }

    /// <summary>
    /// An object (here, usually a state) which has a content in addition to everything else
    /// </summary>
    public interface IContainedObject
    {
        object Content
        {
            get;
        }
    }

    //************************************************************************************************

    /// <summary>
    /// :Or IStorable
    /// A state variable should be "string", Primitive type, enum, or "IStateVariable".
    /// This interface is the least condition to generate the state space.
    /// <para>It is recommended to also implement method "ToString()" xplicitely, 
    /// but of course it is not mandatory and the system can always use the basic ToString() defined for all objects</para>
    /// </summary>
    public interface IStateVariable : ICloneable
    {
        /// <summary>
        /// Should be overriden!
        /// </summary>
        /// <param name="obj">The object to be compared</param>
        /// <returns>true if this object is equal to "obj", false in other case</returns>
        bool Equals(object obj);

        /// <summary>
        /// Get Hash Code of the object
        /// Should be overriden!
        /// </summary>
        /// <returns></returns>
        int GetHashCode();
    }


    /// <summary>
    /// The content of state (which includes a set of state variables, implemented explicitily)
    /// Here, we do not force user to implement all methods of IStateContent and one should (at least) implement Equals and Clone method.
    /// However. in some other modules, we use these methodss
    /// </summary>
    public interface IStateContent : IComparable, IStateVariable
    {
        //* It was IState before!

        //int CompareTo(object obj);//->Implemented in IComparable

        /// <summary>
        /// List of fields in the state
        /// </summary>
        object[] Fields
        {
            get;
        }

        /// <summary>
        /// Number of fields
        /// </summary>
        int LocationValuesCount { get; }

        /// <summary>
        /// Name of "i"th location of the state
        /// </summary>
        /// <param name="locationId"></param>
        /// <returns></returns>
        string GetLocationName(int locationId);


        /// <summary>
        /// Content of location "i"
        /// </summary>
        /// <param name="locationId"></param>
        /// <returns></returns>
        object GetLocation(int locationId);
    }



    /// <summary>
    /// We suggest to use IStateContent as the content and ITransition as transition
    /// </summary>
    public interface IStateContainer : IState<object>
    {
        /// <summary>
        /// Content of the state (better to define them as IStateContent)
        /// </summary>
        object content
        {
            get;
        }

        /// <summary>
        /// Identifier should be uniqe (it is used in exporting and imorting methods).
        /// It is usually implemented as an incrementing integer
        /// </summary>
        object Identifier
        {
            get;
        }
    }
}
